package be.ipl.Diavolo.uccImpl;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Stateless;

import be.ipl.Diavolo.dao.JoueurDao;
import be.ipl.Diavolo.dao.PartieDao;
import be.ipl.Diavolo.domaine.Joueur;
import be.ipl.Diavolo.domaine.Partie;
import be.ipl.Diavolo.domaine.Partie.Etat;
import be.ipl.Diavolo.exceptions.ArgumentInvalideException;
import be.ipl.Diavolo.exceptions.JoueurInexistantException;
import be.ipl.Diavolo.exceptions.PartieEnCoursException;
import be.ipl.Diavolo.exceptions.PartieExistanteException;
import be.ipl.Diavolo.exceptions.PartieFinieException;
import be.ipl.Diavolo.exceptions.PartieInexistanteException;
import be.ipl.Diavolo.exceptions.VainqueurInexistantException;
import be.ipl.Diavolo.ucc.GestionPartie;
import be.ipl.Diavolo.util.Util;

@Stateless
public class GestionPartieImpl implements GestionPartie {

	private Partie partie;

	@EJB
	JoueurDao joueurDao;
	@EJB
	PartieDao partieDao;

	@Override
	public boolean creerPartie(String nom, Joueur joueur)
			throws ArgumentInvalideException, PartieExistanteException {
		if (Util.checkNullEmpty(nom))
			throw new ArgumentInvalideException();
		if (!Util.checkNull(this.partie))
			throw new PartieExistanteException();
		this.partie = new Partie(nom);
		this.partie.ajouterJoueur(joueur);
		this.partie = this.partieDao.enregistrer(this.partie);
        return true;
	}
	
	@Override
	public boolean rejoindrePartie(String pseudo) throws PartieFinieException,
			PartieEnCoursException, PartieInexistanteException,
			JoueurInexistantException {
		if (partie == null)
			throw new PartieInexistanteException();
		if (partie.getEtat() == Etat.EN_COURS)
			throw new PartieEnCoursException();
		if (partie.getEtat() == Etat.FINIE)
			throw new PartieFinieException();
		partie = partieDao.rechercher(partie.getId());

		Joueur joueur = joueurDao.rechercher(pseudo);
		if (joueur == null) {
			throw new JoueurInexistantException();
		}
		return partie.ajouterJoueur(joueur);
	}

	@Override
	@Lock(LockType.READ)
	public List<String> listerJoueurs() throws PartieInexistanteException {
		if (Util.checkNull(this.partie))
			throw new PartieInexistanteException();
		List<Joueur> js = partie.getJoueurs();
		List<String> pseudos = new ArrayList<String>();
		for (Joueur j : js)
			pseudos.add(j.getPseudo());
		return pseudos;
	}

	@Override
	public boolean commencerPartie() throws PartieInexistanteException {
		if (Util.checkNull(this.partie))
			throw new PartieInexistanteException();
		if (partie.getEtat() != Etat.INITIAL)
			return false;
		this.partie = partieDao.rechercher(partie.getId());
		return partie.commencerPartie();
	}

	@Override
	@Lock(LockType.READ)
	public int nbBieres(String pseudo) throws PartieInexistanteException {
		if (Util.checkNull(this.partie))
			throw new PartieInexistanteException();
		this.partie = partieDao.rechercher(partie.getId());
		return partie.getNbBiere(partie.getJoueur(pseudo));
	}

	@Override
	public boolean auSuivant() throws PartieInexistanteException {
		if (Util.checkNull(this.partie))
			throw new PartieInexistanteException();
		this.partie = partieDao.rechercher(partie.getId());
		return partie.commencerTourSuivant();
	}

	@Override
	public String vainqueur() throws PartieInexistanteException,
			VainqueurInexistantException {
		if (Util.checkNull(this.partie))
			throw new PartieInexistanteException();
		this.partie = partieDao.rechercher(partie.getId());
		Joueur v = partie.getVainqueur();
		if (Util.checkNull(v))
			throw new VainqueurInexistantException();
		return v.getPseudo();
	}

	@Override
	public boolean estFinie() throws PartieInexistanteException {
		if (Util.checkNull(this.partie))
			throw new PartieInexistanteException();
		this.partie = partieDao.rechercher(partie.getId());
		return this.partie.getEtat() == Etat.FINIE;
	}

	@Override
	public void annulerPartie() throws PartieInexistanteException {
		if (Util.checkNull(this.partie))
			throw new PartieInexistanteException();
		partie.annuler();
	}

	@Override
	public List<Partie> listerParties() {
		return this.partieDao.listerParties();
	}

	@Override
	public Partie rechercherPartie(int idPartie) {
		return partieDao.rechercher(partie.getId());
	}
}
